import requests
import json
import base64
import hashlib
import hmac
import time
from typing import Optional, Dict, Any
import wave
import io


class TTSClient:
    def __init__(self, app_id: str, app_secret: str, base_url: str = "http://192.168.102.28:37090/open/tts/short"):
        self.app_id = app_id
        self.app_secret = app_secret
        self.base_url = base_url

    def _generate_signature(self, timestamp: str) -> str:
        """生成签名"""
        # 根据API文档调整签名生成逻辑
        message = f"{self.app_id}{timestamp}"
        signature = hmac.new(
            self.app_secret.encode('utf-8'),
            message.encode('utf-8'),
            hashlib.sha256
        ).hexdigest()
        return signature

    def _generate_authorization(self, timestamp: str) -> str:
        """生成Authorization头"""
        signature = self._generate_signature(timestamp)
        return f"Access={self.app_id},Signature={signature}"

    def synthesize_speech(
            self,
            text: str,
            fs: int = 8000,
            format: str = "PCM",
            speed: Optional[float] = None,
            pitch: Optional[float] = None,
            volume: Optional[float] = None,
            read_timeout: Optional[int] = None,
            save: bool = False
    ) -> Dict[str, Any]:
        """
        合成语音

        Args:
            text: 需要合成的文本
            fs: 音频采样率 (8000或16000)
            format: 音频格式 (PCM, ULAW, ALAW)
            speed: 语速 (0.8-1.2)
            pitch: 变调
            volume: 音量增益 (0.5-5.0)
            read_timeout: 服务器超时时间
            save: 是否保存合成记录
        """
        # 验证参数
        if fs not in [8000, 16000]:
            raise ValueError("fs must be 8000 or 16000")

        if format not in ["PCM", "ULAW", "ALAW"]:
            raise ValueError("format must be PCM, ULAW or ALAW")

        # 准备请求数据
        data = {
            "text": text,
            "fs": fs,
            "format": format,
            "save": save
        }

        # 添加可选参数
        if speed is not None:
            data["speed"] = speed
        if pitch is not None:
            data["pitch"] = pitch
        if volume is not None:
            data["volume"] = volume
        if read_timeout is not None:
            data["readTimeOut"] = read_timeout

        # 生成时间戳和签名
        timestamp = str(int(time.time() * 1000))

        # 设置请求头
        headers = {
            "Content-Type": "application/json",
            "Authorization": self._generate_authorization(timestamp)
        }

        try:
            # 发送请求
            response = requests.post(
                self.base_url,
                json=data,
                headers=headers,
                timeout=30
            )

            # 解析响应
            result = response.json()

            if result.get("code") == 200:
                return {
                    "success": True,
                    "audio_data": result["data"]["content"],
                    "message": result.get("msg", "请求成功")
                }
            else:
                return {
                    "success": False,
                    "error_code": result.get("code"),
                    "message": result.get("msg", "请求失败")
                }

        except requests.exceptions.RequestException as e:
            return {
                "success": False,
                "error_code": "NETWORK_ERROR",
                "message": f"网络请求失败: {str(e)}"
            }
        except json.JSONDecodeError as e:
            return {
                "success": False,
                "error_code": "JSON_ERROR",
                "message": f"响应解析失败: {str(e)}"
            }

    def save_audio_to_file(self, base64_audio: str, filename: str):
        """
        将Base64编码的音频数据保存为文件

        Args:
            base64_audio: Base64编码的音频数据
            filename: 输出文件名
            format: 音频格式
            fs: 采样率
        """
        # 解码Base64数据
        audio_bytes = base64.b64decode(base64_audio)

        with open(f'outputs/{filename}', 'wb') as f:
            f.write(audio_bytes)

        print(f"音频已保存到: {filename}")


def main():
    # 配置信息 - 请替换为您的实际信息
    APP_ID = "15"
    APP_SECRET = "your_app_secret"

    # 创建客户端
    client = TTSClient(APP_ID, APP_SECRET)

    # 测试文本
    test_text = "欢迎使用语音合成服务，这是一个测试示例。"

    print("开始合成语音...")

    # 调用TTS API
    result = client.synthesize_speech(
        text=test_text,
        fs=16000,  # 采样率
        format="PCM",  # 音频格式
        speed=1.0,  # 语速
        volume=1.0,  # 音量
        read_timeout=10,  # 超时时间
        save=False  # 不保存记录
    )

    if result["success"]:
        print("语音合成成功!")

        # 保存音频文件
        audio_filename = "output_audio.wav"
        client.save_audio_to_file(
            result["audio_data"],
            audio_filename
        )


    else:
        print(f"语音合成失败: {result['message']} (错误码: {result.get('error_code', '未知')})")


if __name__ == "__main__":
    main()